In both mathematical and programming world, the term “Currying” is often mentioned as the process of transforming a function which takes multiple arguments into a sequence of functions that each has only a single parameter. In other words, it describes that every function essentially is mapped to an expression that consists of anonymous functions, nested anonymous functions and each taking just one parameter.
The concept of “Currying” may be explained simpler by showing you the following comparisons.
In programming, “Currying” could mean as simple as,
which mathematically is pretty much same as writing,
Note how the function breaks down into a multiple of one-argument functions which each gets executed separately in all in a single call of “Currying” (first code).
Let us dive into an example right away. We are going to write a function called sum
to describe both the concept of “Currying” and “partially applied function”. Partially applied functions are important to be mentioned here along with Currying because they consist of similar concepts but not exactly the same.
sum
function is a great example to show “Currying” behaviour because the function could be used in different ways of summing such as multiplications, additions, divisions, subtractions, representing other complex values. This is the key of “Currying”. This chameleon-like sum
function can be applied to various different situations which leave us room for organizing/refactoring the codes.
Let’s initially define the sum
function like this below.
Now we can define the following functions which use the generic sum
function we defined above.
You may have noticed that above functions have repeated a
and b
parameters which get passed into our sum
function. They seem to be unnecessary and can probably be simpler.
Could there be a way to remove these out? There must be a way to simplify the above functions. Well, that’s when the technique of “Currying” applies. Let me show you a step-by-step of the transformation we could make to simplify this using “Currying”.
Let’s update our sum
function to return a function instead, (Int, Int) => Int.
When we’ve done that, we can simply define sumInts
and sumCubes
as themselves a function.
where we can use it like below. It will aggregate values from 1 to 5 (15) and add it to the aggregate of cubed values from 3 to 5 (216) which would be equal to 15+216=231.
Now can we avoid even these names sumInts
and sumCubes
and straight use our sum
function instead? After all, they are basically using the core function, sum
. The answer is “Yes” and that is where “Currying” kicks in.
We can pass in a function to our sum with values attached beside the function which is equivalent to sumInts(1,5) + sumCubes(3,5)
we defined above like this.
This is what the Currying is in a nutshell. Being able to pass in different sets of parameters to execute the function in a specific way we want it function.
We have analyzed a rather a long explained step-by-step example of Currying above. To simply put, you could think of a function like this doSomething(10,“Hello”, true)
which essentially is doSomething(10)(“Hello”)(true)
. It basically is calling doSomething function with anonymous functions 3 times.
I’ve mentioned above there are subtle differences between “Currying” and “Partially applied functions”. They are very similar but not exactly the same. Partial application is slightly different from Currying in that it takes the argument(s), applies it partially and returns a new function without the passed parameter. To see what it means, I will show an example using the exactly the same example as above. Let’s make a new rule (for argument sake) that the above sum
function gets an upper bound of fixed 5.
We have partially created a function here which can take a lower bound as any inputs but has fixed upper bound of 5. To apply this partially created function,
At this point, you might wonder, what is the advantage of doing all this? To be honest, I have not come across a time where I was absolutely required to use Currying to make something work. This is probably why a lot of people thinks Currying is just another syntactic sugar for functional programming. I do not disagree. It could well be a syntactic sugar despite a possible grain of performance gains which may not even be noticeable. However, Currying is still an important concept to understand in functional programming.
In my work experiences in Scala, I have witnessed Currying being used (quite effectively) for organizing purposes where it was much clearer that codes are doing some extra filterings in different functions before the actual “ready” content is passed in the main function which is cleaner than writing everything in one place.
For partially applied functions, as the name suggests, it is useful when you aren’t sure what the other value of a function is. If you are adding a + b
, say you already know of value a
, but b
is unknown. then you can partially make up the function which adds a
then you can add b
when it’s ready later by applying the new function we created earlier which adds a
.